#include "commandutils.h"

#include <sys/wait.h>

#include "core.h"
#include "fileutils.h"

// not avaliable
bool waitToFinish(FILE *fp) {
    if (!fp) return false;
    
    int status = pclose(fp);

    if (WIFEXITED(status)) {
        INFO_LOG("进程已退出");
        DEBUG_LOG("退出状态: %d", WEXITSTATUS(status));
        if (WEXITSTATUS(status) == 0) {
            DEBUG_LOG("指令执行成功");
            return true;
        } else {
            WARNING_LOG("指令执行失败: %d", WEXITSTATUS(status));
            return false;
        }
    } else {
        WARNING_LOG("指令执行返回值: %d", WEXITSTATUS(status));
        return false;
    }
}

bool foundCommand(char *cmd) {
    if (isNull(cmd)) return false;
    
    errno = 0;
    int status;
    char buffer[1] = {0};
    
    char _cmd[100] = {"which "};
    strcat(_cmd, cmd);

    FILE *fp = NULL;
    if ((fp = popen(_cmd, "r")) == NULL) {
        ERROR_LOG("错误信息： %s",strerror(errno));
        return false;
    }

    
    fread(buffer, 1, sizeof(buffer), fp);  // 尝试读取一个字节，来保证popen最终执行。

    status = pclose(fp);

    // DEBUG_LOG("执行(%s)",_cmd);
    if (status == -1) {
        ERROR_LOG("错误信息：fork 失败");
        return false;
    } else {
        if (WIFEXITED(status)) {
            // DEBUG_LOG("进程退出状态: %d", WEXITSTATUS(status));
            if (WEXITSTATUS(status) == 0) {
                // DEBUG_LOG("指令执行成功");
                return true;
            } else {
                // ERROR_LOG("指令执行失败: %d", WEXITSTATUS(status));
                return false;
            }
        } else {
            // WARNING_LOG("指令执行返回值: %d", WEXITSTATUS(status));
            return false;
        }
    }
    return true;
}

// only line stdout
bool getCmdStdoutLine(char *cmd, char *buffer) {
    if (isNull(cmd)) return false;

    FILE *fp = NULL;
    if ((fp = popen(cmd, "r")) == NULL) {
        ERROR_LOG("错误信息： %s",strerror(errno));
        return false;
    }

    freadline(fp, buffer);

    pclose(fp);

    return true;
}

// only read stdout of len
bool getCmdStdoutFull(char *cmd, char *buffer, size_t len) {
    if (isNull(cmd)) return false;

    FILE *fp = NULL;
    if ((fp = popen(cmd, "r")) == NULL) {
        ERROR_LOG("错误信息： %s",strerror(errno));
        return false;
    }

    // freadline(fp, buffer);
    fread(buffer, 1, len-1, fp);

    pclose(fp);

    return true;
}


// ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
// │ WIFEXITED(status)                                                                                                    │
// │     True if the process terminated normally by a call to _exit(2) or exit(3).                                        │
// ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
// │ WIFSIGNALED(status)                                                                                                  │
// │     True if the process terminated due to receipt of a signal.                                                       │
// ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
// │ WIFSTOPPED(status)                                                                                                   │
// │     True if the process has not terminated, but has stopped and can be restarted.  This macro can be true only if    │
// │ the wait call specified the WUNTRACED option or if the child process is                                              │
// │ being traced (see ptrace(2)).                                                                                        │
// ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
// │ Depending on the values of those macros, the following macros produce the remaining status information about the     │
// │ child process:                                                                                                       │
// ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
// │ WEXITSTATUS(status)                                                                                                  │
// │     If WIFEXITED(status) is true, evaluates to the low-order 8 bits of the argument passed to _exit(2) or exit(3)    │
// │ by the child.                                                                                                        │
// ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
// │ WTERMSIG(status)                                                                                                     │
// │     If WIFSIGNALED(status) is true, evaluates to the number of the signal that caused the termination of the         │
// │ process.                                                                                                             │
// ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
// │ WCOREDUMP(status)                                                                                                    │
// │     If WIFSIGNALED(status) is true, evaluates as true if the termination of the process was accompanied by the       │
// │ creation of a core file containing an image of the process when the signal                                           │
// │ was received.                                                                                                        │
// ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
// │ WSTOPSIG(status)                                                                                                     │
// │     If WIFSTOPPED(status) is true, evaluates to the number of the signal that caused the process to stop.            │
// └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘